<?php

/**
 * 微信模板消息接口
 * Class TemplateMessage
 * 微信模板消息开发文档 https://mp.weixin.qq.com/wiki/5/6dde9eaa909f83354e0094dc3ad99e05.html
 * (请求和返回都在这里, 请仔细阅读, 在文档中不在赘述)
 * @author lilei<LL_strive@163.com> 2017-04-28
 */
class TemplateMessage {

    /**
     * 微信公众平台申明的模板消息行业信息, 目前已设置41个(2017-05-27)
     * @var array
     */
    protected static $arr_industries = [
        'IT科技_互联网|电子商务'     => 1,
        'IT科技_IT软件与服务'       => 2,
        'IT科技_IT硬件与设备'       => 3,
        'IT科技_电子技术'           => 4,
        'IT科技_通信与运营商'        => 5,
        'IT科技_网络游戏'           => 6,
        '金融业_银行'              => 7,
        '金融业_基金|理财|信托'      => 8,
        '金融业_保险'              => 9,
        '餐饮_餐饮'                => 10,
        '酒店旅游_酒店'            => 11,
        '酒店旅游_旅游'            => 12,
        '运输与仓储_快递'           => 13,
        '运输与仓储_物流'           => 14,
        '运输与仓储_仓储'           => 15,
        '教育_培训'                => 16,
        '教育_院校'                => 17,
        '政府与公共事业_学术科研'     => 18,
        '政府与公共事业_交警'        => 19,
        '政府与公共事业_博物馆'      => 20,
        '政府与公共事业_公共事业|非盈利机构'    => 21,
        '医药护理_医药医疗'         => 22,
        '医药护理_护理美容'         => 23,
        '医药护理_保健与卫生'        => 24,
        '交通工具_汽车相关'         => 25,
        '交通工具_摩托车相关'        => 26,
        '交通工具_火车相关'         => 27,
        '交通工具_飞机相关'         => 28,
        '房地产_建筑'              => 29,
        '房地产_物业'              => 30,
        '消费品_消费品'            => 31,
        '商业服务_法律'            => 32,
        '商业服务_会展'            => 33,
        '商业服务_中介服务'         => 34,
        '商业服务_认证'            => 35,
        '商业服务_审计'            => 36,
        '文体娱乐_传媒'            => 37,
        '文体娱乐_体育'            => 38,
        '文体娱乐_娱乐休闲'         => 39,
        '印刷_印刷'               => 40,
        '其它_其它'               => 41
    ];

    /**
     * 设置所属行业
     *
     * @param string $cid
     * @param string $industry_id1
     * @param string $industry_id2
     * @return mixed|void
     */
    public static function apiSetIndustry($cid, $industry_id1, $industry_id2)
    {
        $url = 'https://api.weixin.qq.com/cgi-bin/template/api_set_industry?access_token=';
        $postData = [
            'industry_id1' => $industry_id1,
            'industry_id2' => $industry_id2
        ];

        // 从接口上看不出请求返回的result值结构, 后续添加吧
        $result = self::tmCurl($cid, $url, 'POST', $postData, FALSE);
        return $result;
    }

    /**
     * 获取设置的行业信息
     *
     * @param string $cid
     * @return mixed|void
     */
    public static function getIndustry($cid)
    {
        $url = 'https://api.weixin.qq.com/cgi-bin/template/get_industry?access_token=';

        /**
         * {
         *   "primary_industry": {
         *       "first_class": "IT科技",
         *       "second_class": "互联网|电子商务"
         *   },
         *   "secondary_industry": {
         *       "first_class": "IT科技",
         *       "second_class": "IT软件与服务"
         *   }
         * }
         */
        $industries = self::tmCurl($cid, $url, 'GET', [], FALSE);

        // 将中文转出对应的industry_id
        foreach ($industries as $industry_id => $industry) {
            $industry->industry_id = self::$arr_industries[$industry->first_class . '_' . $industry->second_class];
        }
        /**
         *   {
         *       "primary_industry": {
         *           "first_class": "IT科技",
         *           "second_class": "互联网|电子商务",
         *           "industry_id": 1
         *       },
         *       "secondary_industry": {
         *           "first_class": "IT科技",
         *           "second_class": "IT软件与服务",
         *           "industry_id": 2
         *       }
         *   }
         */

        return $industries;
    }

    /**
     * 获得模板ID(容易误解"获得"的意思, 这个获得是微信公众号相对微信平台而言, 就是将相应的模板加到公众号中)
     *
     * @param string $cid
     * @param string $template_id_short 模板的简短编号值('TM00015')
     * @return mixed|void
     */
    public static function apiAddTemplate($cid, $template_id_short)
    {
        $url = 'https://api.weixin.qq.com/cgi-bin/template/api_add_template?access_token=';
        $postData = [
            'template_id_short' => $template_id_short
        ];

        /**
         * 这个请求结果是一定得要的, 因为这里有模板id返回
         *  {
         *      "errcode":0,
         *      "errmsg":"ok",
         *      "template_id":"Doclyl5uP7Aciu-qZ7mJNPtWkbkYnWBWVja26EGbNyk"
         *  }
         */
        $result = self::tmCurl($cid, $url, 'POST', $postData, FALSE);
        return $result;
    }

    /**
     * 获取模板列表
     *
     * @param string $cid
     * @return mixed|void
     */
    public static function getAllPrivateTemplate($cid)
    {
        $url = 'https://api.weixin.qq.com/cgi-bin/template/get_all_private_template?access_token=';

        /**
         * {
         *   "template_list": [
         *       {
         *          "template_id": "IPK6XUYMXfIbkqylsB3fsplrymjz8OVvelTz7c9OzHs",
         *          "title": "订单发货提醒",
         *          "primary_industry": "IT科技",
         *          "deputy_industry": "互联网|电子商务",
         *          "content": "{{first.DATA}}\n订单编号：{{keyword1.DATA}}\n物流公司：{{keyword2.DATA}}\n物流单号：{{keyword3.DATA}}\n{{remark.DATA}}",
         *          "example": "亲，宝贝已经启程了，好想快点来到你身边\r\n订单编号:201408189987\r\n物流公司:圆通快递\r\n物流单号:6522238281\r\n点击查看完整的物流信息 。如有问题请致电XXX或直接在微信里留言，XXX将在第一时间为您服务！"
         *       },
         *       // ...
         *   ]
         * }
         */
        $templates = self::tmCurl($cid, $url, 'GET', [], FALSE);
        return $templates;
    }

    /**
     * 删除模板
     *
     * @param string $cid
     * @param string $template_id   要从微信公众号中删除的模板的模板id('Doclyl5uP7Aciu-qZ7mJNPtWkbkYnWBWVja26EGbNyk')
     * @return mixed|void
     */
    public static function delPrivateTemplate($cid, $template_id)
    {
        $url = 'https://api.weixin.qq.com/cgi-bin/template/del_private_template?access_token=';
        $postData = [
            'template_id' => $template_id
        ];

        /**
         * {"errcode":0,"errmsg":"ok"}
         */
        $result = self::tmCurl($cid, $url, 'POST', $postData, FALSE);
        return $result;
    }

    /**
     * 发送模板消息
     * 开放供平台内部统一调用微信模板消息的接口
     *
     * @param string $toUser   将信息发送给谁(user的openId)
     * @param string $cid      微信公众号->对应咱们后台账号的cid
     * @param string $type     具体发送哪调模板消息(根据type去wx_29_template_messages中查找-->需要cid)
     * @param string $url      点击消息跳转的URL(肯定由调用者传入)
     * @param array  $data     发送的消息内容(肯定由调用者传入)
     */
    public static function send($toUser, $cid, $type, $url, $data)
    {
        /** 1. 根据$cid, $type去响应的wx_29_template_messages去拿$template_id */
        Session::switchCustomer($cid);
        $templateModel = M('template_messages');
        $templatemsg = $templateModel->where(['status' => $type])->find();
        $template_id = $templatemsg['templateId'];

        $topcolor = '#FF0000';  // (无用参数)
        // 最后参数false, 使模板消息错误不打印
        WeixinApi::sendTpl($toUser, $template_id, $url, $topcolor, $data, FALSE, $cid);
    }

    /**
     * 事件推送 - 微信 => 开发者
     * 在模版消息发送任务完成后，微信服务器会将是否送达成功作为通知，发送到开发者中心中填写的服务器配置地址中。
     */

    /*
    |--------------------------------------------------------------------------
    |                           以下为该类私有方法
    |--------------------------------------------------------------------------
    */

    /**
     * curl请求调用微信接口
     *
     * @param int    $cid
     * @param string $url            请求相应的微信接口URL
     * @param string $requestMode    HTTP请求方式[GET|POST|...]
     * @param array  $message        目前为POST请求方式下的数据
     * @param bool   $printErr       此期间, 如果有错误是否输出至页面(主要是获取TOKEN时错误)
     * @return mixed|void
     * curl中文文档: http://php.net/manual/zh/function.curl-setopt.php
     */
    private function tmCurl($cid, $url, $requestMode, $message = array(), $printErr = FALSE)
    {
        /** 0. 获得请求微信的TOKEN */
        $accessToken = WeixinApi::getAccessToken($printErr, $cid);
        if (!$accessToken) {
            return;
        }

        $url = $url . $accessToken;
        /** 1. 初始化, 新建一个curl资源 */
        $ch = curl_init() ;

        /** 2. 设置URL和相应的选项 */
        // 2.1 需要获取的 URL 地址，也可以在curl_init() 初始化会话的时候。
        curl_setopt($ch, CURLOPT_URL, $url);
        // 2.2 启用时会将头文件的信息作为数据流输出。
        curl_setopt($ch, CURLOPT_HEADER, 0);
        // 2.3 请求方式
        switch (strtoupper($requestMode)) {
            case 'POST':
                curl_setopt($ch, CURLOPT_POST, 1);
                break;
            case 'GET':
                break;
            default:
                break;
        }
        // 2.4 如果是POST请求方式, 设置post的值
        if (strtoupper($requestMode) == 'POST') {
            curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($message));
        }
        // 2.5 FALSE 禁止 cURL 验证对等证书（peer's certificate）
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        // 2.6 公用名检查: [0|1|2(默认)]
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
        // 2.7 TRUE 将curl_exec()获取的信息以字符串返回，而不是直接输出。
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
        // 2.8 允许 cURL 函数执行的最长秒数。
        curl_setopt($ch, CURLOPT_TIMEOUT, 5);

        /** 3. 执行CURL操作 */
        // 3.1 抓取URL并把它传递给浏览器
        $result = curl_exec($ch);
        // 3.2 抓取URL出现错误的情况
        $error = curl_errno($ch);
        if ($error) {
            \Log::write('TemplateMessage::tmCurl()->202' . json_encode($error));
        }

        /** 4. 关闭cURL资源，并且释放系统资源 */
        curl_close($ch);

        /** 5. 返回结果 */
        $result = json_decode($result);
        return $result;
    }

}
